import {
    AbilityType,
    APIType,
    APIVersion, CURRENT_HMOS_API,
    LanguageType,
    ModuleTemplateType,
    RuntimeOSType
} from '../../../../../models/constants';
import { ModuleTemplateOption, ModuleTemplateOptionBuilder } from '../../../../../models/model-options';
import { ModuleConfigInitFun } from '../../../../../models/module-models';
import { copyTmp, DirTemplateCreator, dirTmp, renderTmp } from '../../../../../models/template-models';
import { entryBuilder, moduleBuilder } from '../../../../../module-builder';

/**
 * EmptyAbility
 *
 * @type {ModuleTemplateOption}
 */
const entryOption: ModuleTemplateOption = ModuleTemplateOptionBuilder.builder()
  .abilityType(AbilityType.Application)
  .apiType(APIType.FA)
  .apiVersion(CURRENT_HMOS_API)
  .language(LanguageType.ArkTs)
  .moduleTemplateType(ModuleTemplateType.EmptyAbility)
  .runtimeOS(RuntimeOSType.HarmonyOS)
  .build();

const entryTemplate: DirTemplateCreator = (dirName) => dirTmp(dirName)
  .add(dirTmp('src')
    .add(dirTmp('main')
      .add(copyTmp('/module/fa/app/common/src/main/ets'))
      .add(copyTmp('/module/fa/app/common/src/main/resources'))
      .add(renderTmp('/module/fa/app/common/src/main/config.json'))
    )
    .add(dirTmp('ohosTest')
      .add(copyTmp('/module/fa/app/common/src/ohosTest/ets'))
      .add(copyTmp('/module/fa/app/common/src/ohosTest/resources'))
      .add(renderTmp('/module/fa/app/common/src/ohosTest/config.json'))
    )
  )
  .add(renderTmp('/entry/fa/app/emptyAbility/api16/build-profile.json5'))
  .add(copyTmp('/entry/fa/app/emptyAbility/api16/hvigorfile.ts'))
  .add(renderTmp('/entry/fa/app/emptyAbility/api16/oh-package.json5'));


const initFun: ModuleConfigInitFun = async (name, option, template) => {
  template.node('src').node('main').node('config.json')
    .data = { moduleName: name, moduleType: 'entry' };
  template.node('src').node('ohosTest').node('config.json')
    .data = { moduleName: name, moduleType: 'feature' };
  template.node('build-profile.json5').data = { apiType: option.apiType };
  template.node('oh-package.json5').data = { moduleName: name };
};

entryBuilder.add(entryOption, entryTemplate, initFun);

/**
 * EmptyAbility
 *
 * @type {ModuleTemplateOption}
 */
const emptyAbilityOption: ModuleTemplateOption = ModuleTemplateOptionBuilder.builder()
  .abilityType(AbilityType.Application)
  .apiType(APIType.FA)
  .apiVersion(CURRENT_HMOS_API)
  .language(LanguageType.ArkTs)
  .moduleTemplateType(ModuleTemplateType.EmptyAbility)
  .runtimeOS(RuntimeOSType.HarmonyOS)
  .build();

const entryAbilityTemplate: DirTemplateCreator = (dirName) => dirTmp(dirName)
  .add(dirTmp('src')
    .add(dirTmp('main')
      .add(copyTmp('/module/fa/app/common/src/main/ets'))
      .add(copyTmp('/module/fa/app/common/src/main/resources'))
      .add(renderTmp('/entry/fa/app/emptyAbility/api16/src/main/config.json'))
    )
    .add(dirTmp('ohosTest')
      .add(copyTmp('/module/fa/app/common/src/ohosTest/ets'))
      .add(copyTmp('/module/fa/app/common/src/ohosTest/resources'))
      .add(renderTmp('/module/fa/app/common/src/ohosTest/config.json'))
    )
  )
  .add(renderTmp('/module/fa/app/common/build-profile.json5'))
  .add(copyTmp('/entry/fa/app/emptyAbility/api16/hvigorfile.ts'))
  .add(renderTmp('/entry/fa/app/emptyAbility/api16/oh-package.json5'));

const EmptyAbilityinitFun: ModuleConfigInitFun = async (name, option, template) => {
  template.node('src').node('main').node('config.json')
    .data = { moduleName: name, moduleType: 'feature' };
  template.node('src').node('ohosTest').node('config.json')
    .data = { moduleName: name, moduleType: 'feature' };
  template.node('build-profile.json5').data = { apiType: option.apiType };
  template.node('oh-package.json5').data = { moduleName: name };
};

moduleBuilder.add(emptyAbilityOption, entryAbilityTemplate, EmptyAbilityinitFun);

/**
 * NativeC
 *
 * @type {ModuleTemplateOption}
 */

const nativeAbilityOption: ModuleTemplateOption = ModuleTemplateOptionBuilder.builder()
  .abilityType(AbilityType.Application)
  .apiType(APIType.FA)
  .apiVersion(CURRENT_HMOS_API)
  .language(LanguageType.ArkTs)
  .moduleTemplateType(ModuleTemplateType.NativeC)
  .runtimeOS(RuntimeOSType.HarmonyOS)
  .build();

const nativeAbilityTemplate: DirTemplateCreator = (dirName) => dirTmp(dirName)
  .add(dirTmp('libs')
    .add(dirTmp('armeabi-v7a'))
  )
  .add(dirTmp('src')
    .add(dirTmp('main')
      .add(dirTmp('cpp')
        .add(dirTmp('types')
          .add(dirTmp('libapplication')
            .add(copyTmp('module/fa/app/nativeApplication/api16/src/main/cpp/types/libapplication/index.d.ts'))
            .add(renderTmp('module/fa/app/nativeApplication/api16/src/main/cpp/types/libapplication/oh-package.json5'))
          )
        )
        .add(renderTmp('module/fa/app/nativeApplication/api16/src/main/cpp/CMakeLists.txt'))
        .add(renderTmp('module/fa/app/nativeApplication/api16/src/main/cpp/hello.cpp'))
      )
      .add(dirTmp('ets')
        .add(dirTmp('MainAbility')
          .add(copyTmp('module/fa/app/nativeApplication/api16/src/main/ets/MainAbility/pages'))
          .add(copyTmp('module/fa/app/common/src/main/ets/MainAbility/app.ets'))
        )
      )
      .add(copyTmp('/module/fa/app/common/src/main/resources'))
      .add(renderTmp('/module/fa/app/common/src/main/config.json'))
    )
    .add(dirTmp('ohosTest')
      .add(copyTmp('/module/fa/app/common/src/ohosTest/ets'))
      .add(copyTmp('/module/fa/app/common/src/ohosTest/resources'))
      .add(renderTmp('/module/fa/app/common/src/ohosTest/config.json'))
    )
  )
  .add(renderTmp('/module/fa/app/nativeApplication/api16/build-profile.json5'))
  .add(copyTmp('/module/fa/app/nativeApplication/api16/hvigorfile.ts'))
  .add(renderTmp('/module/fa/app/nativeApplication/api16/oh-package.json5'));

const nativeCInitFun: ModuleConfigInitFun = async (name, option, template) => {
  template.node('src').node('main').node('cpp').node('types')
    .node('libapplication').node('oh-package.json5').data = { moduleName: name };
  template.node('src').node('main').node('cpp').node('CMakeLists.txt')
    .data = { moduleName: name };
  template.node('src').node('main').node('cpp').node('hello.cpp')
    .data = { moduleName: name };
  template.node('src').node('main').node('config.json')
    .data = { moduleName: name, moduleType: 'feature' };
  template.node('src').node('ohosTest').node('config.json')
    .data = { moduleName: name, moduleType: 'feature' };
  template.node('build-profile.json5').data = { apiType: option.apiType };
  template.node('oh-package.json5').data = { moduleName: name };
};

moduleBuilder.add(nativeAbilityOption, nativeAbilityTemplate, nativeCInitFun);

/**
 * NativeC
 *
 * @type {ModuleTemplateOption}
 */

const nativeAbilityEntryOption: ModuleTemplateOption = ModuleTemplateOptionBuilder.builder()
  .abilityType(AbilityType.Application)
  .apiType(APIType.FA)
  .apiVersion(CURRENT_HMOS_API)
  .language(LanguageType.ArkTs)
  .moduleTemplateType(ModuleTemplateType.NativeC)
  .runtimeOS(RuntimeOSType.HarmonyOS)
  .build();

const nativeAbilityEntryTemplate: DirTemplateCreator = (dirName) => dirTmp(dirName)
  .add(dirTmp('libs')
    .add(dirTmp('armeabi-v7a'))
  )
  .add(dirTmp('src')
    .add(dirTmp('main')
      .add(dirTmp('cpp')
        .add(dirTmp('types')
          .add(dirTmp('libentry')
            .add(copyTmp('module/fa/app/nativeApplication/api16/src/main/cpp/types/libapplication/index.d.ts'))
            .add(renderTmp('entry/fa/app/nativeApplication/api16/src/main/cpp/types/libentry/oh-package.json5'))
          )
        )
        .add(renderTmp('module/fa/app/nativeApplication/api16/src/main/cpp/CMakeLists.txt'))
        .add(renderTmp('module/fa/app/nativeApplication/api16/src/main/cpp/hello.cpp'))
      )
      .add(dirTmp('ets')
        .add(dirTmp('MainAbility')
          .add(copyTmp('entry/fa/app/nativeApplication/api16/src/main/ets/MainAbility/pages'))
          .add(copyTmp('module/fa/app/common/src/main/ets/MainAbility/app.ets'))
        )
      )
      .add(copyTmp('/module/fa/app/common/src/main/resources'))
      .add(renderTmp('/module/fa/app/common/src/main/config.json'))
    )
    .add(dirTmp('ohosTest')
      .add(copyTmp('/module/fa/app/common/src/ohosTest/ets'))
      .add(copyTmp('/module/fa/app/common/src/ohosTest/resources'))
      .add(renderTmp('/module/fa/app/common/src/ohosTest/config.json'))
    )
  )
  .add(renderTmp('/entry/fa/app/nativeApplication/api16/build-profile.json5'))
  .add(copyTmp('/module/fa/app/nativeApplication/api16/hvigorfile.ts'))
  .add(renderTmp('/entry/fa/app/nativeApplication/api16/oh-package.json5'));

const nativeCEntryInitFun: ModuleConfigInitFun = async (name, option, template) => {
  template.node('src').node('main').node('cpp').node('types')
    .node('libentry').node('oh-package.json5').data = { moduleName: name };
  template.node('src').node('main').node('cpp').node('CMakeLists.txt')
    .data = { moduleName: name };
  template.node('src').node('main').node('cpp').node('hello.cpp')
    .data = { moduleName: name };
  template.node('src').node('main').node('config.json')
    .data = { moduleName: name, moduleType: 'entry' };
  template.node('src').node('ohosTest').node('config.json')
    .data = { moduleName: name, moduleType: 'feature' };
  template.node('build-profile.json5').data = { apiType: option.apiType };
  template.node('oh-package.json5').data = { moduleName: name };
};

entryBuilder.add(nativeAbilityEntryOption, nativeAbilityEntryTemplate, nativeCEntryInitFun);

/**
 * staticLibrary
 *
 * @type {ModuleTemplateOption}
 */

const staticLibraryAbilityOption: ModuleTemplateOption = ModuleTemplateOptionBuilder.builder()
  .abilityType(AbilityType.Application)
  .apiType(APIType.FA)
  .apiVersion(CURRENT_HMOS_API)
  .language(LanguageType.ArkTs)
  .moduleTemplateType(ModuleTemplateType.StaticLibrary)
  .runtimeOS(RuntimeOSType.HarmonyOS)
  .build();

const staticLibraryAbilityTemplate: DirTemplateCreator = (dirName) => dirTmp(dirName)
  .add(dirTmp('src')
    .add(dirTmp('main')
      .add(copyTmp('module/fa/app/staticLibrary/api16/src/main/ets'))
      .add(copyTmp('module/fa/app/staticLibrary/api16/src/main/resources'))
      .add(renderTmp('module/fa/app/staticLibrary/api16/src/main/config.json'))
    )
  )
  .add(renderTmp('module/fa/app/staticLibrary/api16/build-profile.json5'))
  .add(copyTmp('module/fa/app/staticLibrary/api16/hvigorfile.ts'))
  .add(copyTmp('module/fa/app/staticLibrary/api16/index.ets'))
  .add(renderTmp('module/fa/app/staticLibrary/api16/oh-package.json5'));

const staticLibraryInitFun: ModuleConfigInitFun = async (name, option, template) => {
  template.node('src').node('main').node('config.json').data = { moduleName: name };
  template.node('build-profile.json5').data = { apiType: option.apiType };
  template.node('oh-package.json5').data = { moduleName: name };
};

moduleBuilder.add(staticLibraryAbilityOption, staticLibraryAbilityTemplate, staticLibraryInitFun);

/**
 * StaticLibraryWithC
 *
 * @type {ModuleTemplateOption}
 */

const staticLibraryAbilityWithCOption: ModuleTemplateOption = ModuleTemplateOptionBuilder.builder()
  .abilityType(AbilityType.Application)
  .apiType(APIType.FA)
  .apiVersion(CURRENT_HMOS_API)
  .language(LanguageType.ArkTs)
  .moduleTemplateType(ModuleTemplateType.StaticLibraryWithC)
  .runtimeOS(RuntimeOSType.HarmonyOS)
  .build();

const staticLibraryAbilityWithCTemplate: DirTemplateCreator = (dirName) => dirTmp(dirName)
  .add(dirTmp('libs')
    .add(dirTmp('armeabi-v7a'))
  )
  .add(dirTmp('src')
    .add(dirTmp('main')
      .add(dirTmp('cpp')
        .add(dirTmp('types')
          .add(dirTmp('liblibrary')
            .add(copyTmp('module/fa/app/nativeApplication/api16/src/main/cpp/types/libapplication/index.d.ts'))
            .add(renderTmp('module/fa/app/nativeApplication/api16/src/main/cpp/types/libapplication/oh-package.json5'))
          )
        )
        .add(renderTmp('module/fa/app/staticLibraryWithC/api16/src/main/cpp/CMakeLists.txt'))
        .add(renderTmp('module/fa/app/nativeApplication/api16/src/main/cpp/hello.cpp'))
      )
      .add(copyTmp('module/fa/app/staticLibrary/api16/src/main/ets'))
      .add(copyTmp('module/fa/app/staticLibrary/api16/src/main/resources'))
      .add(renderTmp('module/fa/app/staticLibrary/api16/src/main/config.json'))
    )
  )
  .add(renderTmp('module/fa/app/staticLibraryWithC/api16/build-profile.json5'))
  .add(copyTmp('module/fa/app/staticLibrary/api16/hvigorfile.ts'))
  .add(copyTmp('module/fa/app/staticLibrary/api16/index.ets'))
  .add(renderTmp('module/fa/app/staticLibraryWithC/api16/oh-package.json5'));

const staticLibraryWithCInitFun: ModuleConfigInitFun = async (name, option, template) => {
  template.node('src').node('main').node('cpp').node('types').node('liblibrary')
    .node('oh-package.json5').data = { moduleName: name };
  template.node('src').node('main').node('cpp').node('CMakeLists.txt').data = { moduleName: name };
  template.node('src').node('main').node('cpp').node('hello.cpp').data = { moduleName: name };
  template.node('src').node('main').node('config.json').data = { moduleName: name };
  template.node('build-profile.json5').data = { apiType: option.apiType };
  template.node('oh-package.json5').data = { moduleName: name };
};

moduleBuilder.add(staticLibraryAbilityWithCOption, staticLibraryAbilityWithCTemplate, staticLibraryWithCInitFun);

/**
 * listAbility
 *
 * @type {ModuleTemplateOption}
 */
const listAbilityOption: ModuleTemplateOption = ModuleTemplateOptionBuilder.builder()
  .abilityType(AbilityType.Application)
  .apiType(APIType.FA)
  .apiVersion(CURRENT_HMOS_API)
  .language(LanguageType.ArkTs)
  .moduleTemplateType(ModuleTemplateType.ListAbility)
  .runtimeOS(RuntimeOSType.HarmonyOS)
  .build();

const listAbilityTemplate: DirTemplateCreator = (dirName) => dirTmp(dirName)
  .add(dirTmp('src')
    .add(dirTmp('main')
      .add(copyTmp('module/fa/app/listAbility/api16/src/main/ets'))
      .add(copyTmp('module/fa/app/listAbility/api16/src/main/resources'))
      .add(renderTmp('module/fa/app/listAbility/api16/src/main/config.json'))
    )
    .add(dirTmp('ohosTest')
      .add(copyTmp('module/fa/app/common/src/ohosTest/ets'))
      .add(copyTmp('module/fa/app/common/src/ohosTest/resources'))
      .add(renderTmp('module/fa/app/common/src/ohosTest/config.json'))
    )
  )
  .add(renderTmp('module/fa/app/listAbility/api16/build-profile.json5'))
  .add(copyTmp('module/fa/app/listAbility/api16/hvigorfile.ts'))
  .add(renderTmp('module/fa/app/listAbility/api16/oh-package.json5'));

const listAbilityInitFun: ModuleConfigInitFun = async (name, option, template) => {
  template.node('src').node('main').node('config.json').data = { moduleName: name, moduleType: 'feature' };
  template.node('src').node('ohosTest').node('config.json')
    .data = { moduleName: name, moduleType: 'feature' };
  template.node('build-profile.json5').data = { apiType: option.apiType };
  template.node('oh-package.json5').data = { moduleName: name };
};

moduleBuilder.add(listAbilityOption, listAbilityTemplate, listAbilityInitFun);

/**
 * listEntryAbility
 *
 * @type {ModuleTemplateOption}
 */
const listEntryAbilityOption: ModuleTemplateOption = ModuleTemplateOptionBuilder.builder()
  .abilityType(AbilityType.Application)
  .apiType(APIType.FA)
  .apiVersion(CURRENT_HMOS_API)
  .language(LanguageType.ArkTs)
  .moduleTemplateType(ModuleTemplateType.ListAbility)
  .runtimeOS(RuntimeOSType.HarmonyOS)
  .build();

const listEntryAbilityTemplate: DirTemplateCreator = (dirName) => dirTmp(dirName)
  .add(copyTmp('entry/fa/app/listAbility/api16/src'))
  .add(renderTmp('entry/fa/app/listAbility/api16/build-profile.json5'))
  .add(copyTmp('entry/fa/app/listAbility/api16/hvigorfile.ts'))
  .add(copyTmp('entry/fa/app/listAbility/api16/oh-package.json5'));

const listEntryAbilityInitFun: ModuleConfigInitFun = async (name, option, template) => {
  template.node('build-profile.json5').data = { apiType: option.apiType };
};

entryBuilder.add(listEntryAbilityOption, listEntryAbilityTemplate, listEntryAbilityInitFun);

/**
 * liteEmptyAbility
 *
 * @type {ModuleTemplateOption}
 */
const liteEmptyAbilityEntryOption: ModuleTemplateOption = ModuleTemplateOptionBuilder.builder()
  .abilityType(AbilityType.Application)
  .apiType(APIType.FA)
  .apiVersion(CURRENT_HMOS_API)
  .language(LanguageType.ArkTs)
  .moduleTemplateType(ModuleTemplateType.LiteEmptyAbility)
  .runtimeOS(RuntimeOSType.HarmonyOS)
  .build();

const liteEmptyAbilityEntryTemplate: DirTemplateCreator = (dirName) => dirTmp(dirName)
  .add(dirTmp('src')
    .add(dirTmp('main')
      .add(copyTmp('/entry/fa/app/liteEmptyAbility/api16/src/main/js'))
      .add(copyTmp('/entry/fa/app/liteEmptyAbility/api16/src/main/resources'))
      .add(copyTmp('/entry/fa/app/liteEmptyAbility/api16/src/main/config.json'))
    )
  )
  .add(renderTmp('/entry/fa/app/liteEmptyAbility/api16/build-profile.json5'))
  .add(copyTmp('/entry/fa/app/liteEmptyAbility/api16/hvigorfile.ts'))
  .add(renderTmp('/entry/fa/app/liteEmptyAbility/api16/oh-package.json5'));

const liteEmptyAbilityEntryInitFun: ModuleConfigInitFun = async (name, option, template) => {
  template.node('build-profile.json5').data = { apiType: option.apiType };
  template.node('oh-package.json5').data = { moduleName: name };
};

entryBuilder.add(liteEmptyAbilityEntryOption, liteEmptyAbilityEntryTemplate, liteEmptyAbilityEntryInitFun);

/**
 * jsFaStaticAbility
 *
 * @type {ModuleTemplateOption}
 */
const jsFaStaticAbilityOption: ModuleTemplateOption = ModuleTemplateOptionBuilder.builder()
  .abilityType(AbilityType.Application)
  .apiType(APIType.FA)
  .apiVersion(CURRENT_HMOS_API)
  .language(LanguageType.Js)
  .moduleTemplateType(ModuleTemplateType.JsStaticLibrary)
  .runtimeOS(RuntimeOSType.HarmonyOS)
  .build();

const jsFaStaticAbilityEntryTemplate: DirTemplateCreator = (dirName) => dirTmp(dirName)
  .add(dirTmp('src')
    .add(dirTmp('main')
      .add(copyTmp('module/fa/app/jsStaticLibrary/api16/src/main/js'))
      .add(copyTmp('module/fa/app/jsStaticLibrary/api16/src/main/resources'))
      .add(renderTmp('module/fa/app/jsStaticLibrary/api16/src/main/config.json'))
    )
  )
  .add(renderTmp('module/fa/app/jsStaticLibrary/api16/build-profile.json5'))
  .add(copyTmp('module/fa/app/jsStaticLibrary/api16/hvigorfile.ts'))
  .add(copyTmp('module/fa/app/jsStaticLibrary/api16/index.js'))
  .add(renderTmp('module/fa/app/jsStaticLibrary/api16/oh-package.json5'));

const jsFaStaticAbilityEntryInitFun: ModuleConfigInitFun = async (name, option, template) => {
  template.node('build-profile.json5').data = { apiType: option.apiType };
  template.node('oh-package.json5').data = { moduleName: name };
};

moduleBuilder.add(jsFaStaticAbilityOption, jsFaStaticAbilityEntryTemplate, jsFaStaticAbilityEntryInitFun);
